/////////////////////////////////////////////////////////////////////////////
// Copyright(c) 2012-2015 purang All Rights Reserved
// Name:        message_observer.h
// Purpose:     
// Author:      syy
// Modified by: 
// Created:     2014/7/2 17:54
// RCS-ID:      
// Licence:     
/////////////////////////////////////////////////////////////////////////////
#ifndef _MESSAGE_OBSERVER_H_
#define _MESSAGE_OBSERVER_H_
#include <list>
#include <assert.h>
#include "../common_types.h"
#include "../system/atomic32.h"
#include "../QbLogger.h"
namespace qb
{
#define remove_list_item(iter,obj,verb,del)					\
	if (del && obj._ref == 0)								\
	{														\
		for (iter = obj.begin(); iter != obj.end();)		\
		{													\
			if (!iter->first || iter->second == 0)			\
			{												\
				iter = obj.erase(iter);						\
				continue;									\
			}												\
			++iter;											\
		}													\
	}

#define for_each_list_item(iter,obj,verb)					\
	bool del = false;										\
	obj._ref++;												\
	while(iter != obj.end())								\
	{														\
		if (iter->first && iter->second > 0)				\
		{													\
			verb;											\
		}													\
		else												\
		{													\
			del = true;										\
			iter++;											\
		}													\
	}														\
	obj._ref--;												\
	remove_list_item(iter,obj,verb,del)
	

#define for_each_list(obj,iter,verb) {						\
	for_each_list_item(iter,obj,verb);						\
}

#define for_each_list_item_when_true(iter,obj,verb) 		\
	bool del = false;										\
	obj._ref++;												\
	while(iter != obj.end())								\
	{														\
		if (iter->first && iter->second > 0)				\
		{													\
			if (verb)										\
			{												\
				return true;								\
			}												\
		}													\
		else												\
		{													\
			del = true;										\
			iter++;											\
		}													\
	}														\
	obj._ref--;												\
	remove_list_item(iter,obj,verb,del)

#define for_each_list_when_true(obj,iter,verb) {			\
	for_each_list_item_when_true(iter,obj,verb);			\
}

	template<class T>
	class BList
		: public std::list<std::pair<T,int32_t>>
	{
	public:
		BList()
			:_ref(0)
		{

		}
		int32_t _ref;
	};

	template<typename T> 
	int32_t RegisterObserver(THIS_ T* observer, BList<T*>& arr)
	{
		for (typename BList<T*>::iterator it = arr.begin();it != arr.end(); ++it)
		{
			if (it->first == observer && it->second > 0)
			{
				log_info("object already enabled");
				return -1;
			}
		}

		arr.push_back(std::make_pair(observer,1));

		return 0;
	}

	template<typename T> 
	int32_t DeRegisterObserver(THIS_ T* observer, BList<T*>& arr)
	{
		for (typename BList<T*>::iterator it = arr.begin();it != arr.end(); ++it)
		{
			if (it->first == observer)
			{
				if (arr._ref == 0)
				{
					arr.erase(it);
					return 0;
				}
				else if (it->second > 0)
				{
					it->first = NULL;
					it->second = 0;
					return 0;
				}
			}
		}

		log_info("object already disabled");

		return -1;
	}

	template<typename T> 
	int32_t RemoveObserver(THIS_ BList<T*>& arr, bool nonAssert = false)
	{
		for (typename BList<T*>::iterator it = arr.begin();it != arr.end();)
		{
			if (!it->first || it->second == 0)
			{
				it = arr.erase(it);
				continue;
			}
			++it;
		}

		// non asset
		if (arr.size() != 0 && nonAssert)
		{
			arr.clear();
			return 0;
		}

		// check and assert
		if (arr.size() != 0)
		{
			log_warning("object exist");
        //	assert(0);

			// clear for avoid access security
			arr.clear();
			return -1;
		}
		return 0;
	}

}  // namespace qb


#endif // _MESSAGE_OBSERVER_H_
